#include <stdint.h>
#include <sys/types.h>
#include <sys/time.h>
#include <unistd.h> 
#include <stdlib.h>
#include <assert.h>
#include "app_platform/cntl_info.h"
#include "companydao.h"

#include "c2cplatform/component/dal/dal_set.h"
#include "c2cent/storage/mysqlstorage.h"
#include "c2cplatform/component/dal/db_operator_mysql_set.h"

using namespace c2cplatform::component::dal;
using namespace c2cent::storage;

using namespace erp::company::dao;

CPP_SELF_DEFINE_START
/**
 *  请在这里增加自定义的成员变量和函数及其他内容，否则无法合并代码
 **/
#include "erp/comm/erp_macro_define.h"
#include "erp/comm/erp_errno_define.h"
#define DB_ROLE_NAME_COMPANY  "erp_yun"
#include "c2cplatform/library/string/string_helper.h"
#include "erp/comm/erp_yun_define.h"

using namespace c2cent::library::wtimeelf;
using namespace c2cent::library::wwlog;
using namespace erp::comm;
using namespace c2cplatform::library::string;
using namespace erp::yun::comm;
#define TABLE_NAME_COMPANYREGISTER            "T_CompanyRegister"

//用户企业查询ITIL上报对象初始化
CItilGroup CCompanyDao::m_oGetCompany(GETBANKACCOUNT_REQ, GETBANKACCOUNT_ERR,
		GETBANKACCOUNT_RSP, GETBANKACCOUNT_DEF);

//用户企业ByIds查询ITIL上报对象初始化
CItilGroup CCompanyDao::m_oGetCompanyByIds(GETBANKACCOUNT_REQ,
		GETBANKACCOUNT_ERR, GETBANKACCOUNT_RSP, GETBANKACCOUNT_DEF);

//新增更新用户企业信息ITIL上报对象初始化
CItilGroup CCompanyDao::m_oAddAndUpdateCompany(GETBANKACCOUNT_REQ,
		GETBANKACCOUNT_ERR, GETBANKACCOUNT_RSP, GETBANKACCOUNT_DEF);

//逻辑删除用户企业信息ITIL上报对象初始化
CItilGroup CCompanyDao::m_oDeleteCompany(GETBANKACCOUNT_REQ, GETBANKACCOUNT_ERR,
		GETBANKACCOUNT_RSP, GETBANKACCOUNT_DEF);

CPP_SELF_DEFINE_END

/**
 *构建函数
 */
CCompanyDao::CCompanyDao(enum DeployMethod method)
{
}

/**
 *析构函数
 */
CCompanyDao::~CCompanyDao()
{
}

/**
 *每一次服务请求时，container都会调用此方法来清空数据
 */
void CCompanyDao::Reset()
{
}

int CCompanyDao::Initialize(IUserDefineCntl* pCntl)
{
	int iRet = 0;
	uint32_t dwLogSwitch = WLOG_OPEN | WLOG_KEY_OPEN | WLOG_ERR_OPEN;
	uint32_t dwCanLogRemote = 0;
	std::string strLogModule = "dao_company";

	std::cout << "File:" << __FILE__ << " Complie Date: " << __DATE__ << " "
			<< __TIME__ << std::endl;

	if (CDAL_SET->Initialize() != 0)
	{
		printf("CDAL_SET Init Failed, %s\n", CDAL_SET->getLastErrMsg());
		return -1;
	}

	GetUintConfig(LogSwitch);
	GetStringConfig(LogModule);
	GetUintConfig(CanLogRemote);

	// 初始化日志
	if (C2C_WWLOG->QuickInitForAPP2(strLogModule.c_str(),B2B2CWW_LOG_APP_FILE_PATH, dwCanLogRemote, dwLogSwitch)!= 0)
	{
		std::cerr << "C2C_WWLOG->QuickInitForAPP2 Failed" << std::endl;
		return -1;
	}
	C2C_WW_LOG("C2C_WWLOG->QuickInitForAPP2 OK!");
	return iRet;
}

/**
 *
 *  通过SysNos获取用户企业信息
 *
 *@param String machineKey: 机器码，必填   [in]
 *@param String source: 调用来源，必填   [in]
 *@param uint32_t sceneId: 场景id，必填   [in]
 *@param Set companysysNoList: 用户企业SysNo数组，必填   [in]
 *@param String inReserve: 请求保留字   [in]
 *@param String errmsg: 错误信息  	[out]
 *@param Map companyInfo: 员工信息  	[out]
 *@param String outReserve: 返回保留字   	[out]
 *
 *@return  uint32_t : 0(成功) 其它失败
 *
 */
uint32_t CCompanyDao::GetCompanyByIds(const CCntlInfo& rCntlInfo,
		const std::string& strMachineKey, const std::string& strSource,
		uint32_t dwSceneId, const std::set<uint32_t>& setCompanysysNoList,
		const std::string& strInReserve, std::string& strErrmsg,
		std::map<uint32_t, erp::company::ddo::CCompanyInfoDdo>& mapCompanyInfo,
		std::string& strOutReserve)
{
	uint32_t dwRet = 0;
	//TODO:业务代码

	uint16_t iSetId = 0;
	m_dwOperatorUin = rCntlInfo.getOperatorUin();
	m_dwSceneId = dwSceneId;
	m_strMachineKey = strMachineKey;
	m_strSource = strSource;

	C2C_WW_LOG("GetAReq %s OpUin:%u MachineKey:%s Source:%s SceneId:%u",
			__FUNCTION__, m_dwOperatorUin, strMachineKey.c_str(),
			strSource.c_str(), dwSceneId);

	//打印性能日志的同时进行接口的itil上报
	C2C_TIME_ELF_ITILoWTimeElf(C2C_WWLOG,__FUNCTION__,&dwRet,&m_oGetCompanyByIds);

	//查询SysNo为空，直接返回0
	if (setCompanysysNoList.size() != 0)
	{
		return 0;
	}

	c2cent::storage::CMySqlStorage oStorage(CDAL_SET->GetDBOperator(rCntlInfo.getCmdId(),
			rCntlInfo.getOperatorUin(), DB_ROLE_NAME_COMPANY, TABLE_NAME_COMPANYREGISTER, iSetId, true));
	std::stringstream ssSql;

	ssSql
			<< "SELECT FCompanySysNo,FCompanyName,FCompanyCorporation,FCompanyID,FTableID,FCompanyProperty,FCompanyStatus,";
	ssSql
			<< " FCreatorSysNo,UNIX_TIMESTAMP(FRowCreatDate) ,FModifierSysNo,UNIX_TIMESTAMP(FRowModifyDate) FROM";
	ssSql << " " << TABLE_NAME_COMPANYREGISTER;
	std::stringstream sysNos;

	for (std::set<uint64_t>::iterator it = setCompanysysNoList.begin();
			it != setCompanysysNoList.end(); it++)
	{
		sysNos << *it << ",";
	}
	ssSql << " WHERE FCompanySysNo in (" << Trim(sysNos.str(), ',') << ")";

	//排除已经删除的信息
	ssSql << " AND FCompanyStatus<>0";
	IResultSet& oRs = oStorage.QueryForResultSet(ssSql.str());
	C2C_WW_LOG_DEBUG("ExeSql Passed, Sql:%s", ssSql.str().c_str());
	if (!oRs.IsReady()) //db操作错误
	{
		oRs.Close();
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_SELECT_FAILED, "ExeSql Failed, Sql:%s",
				ssSql.str().c_str());
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_SELECT_FAILED,
				"ExeSql Failed, OpUin:%u MachineKey:%s Source:%s SceneId:%u",
				rCntlInfo.getOperatorUin(), strMachineKey.c_str(),
				strSource.c_str(), dwSceneId);
		C2C_WW_LOG_LAST_ERR_LOG(strErrmsg);
		return ERR_ERP_COMMON_DB_SELECT_FAILED;
	}

	if (!oRs.First() || oRs.GetRecordCount() == 0) //无记录
	{
		oRs.Close();
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_SELECT_FAILED, "ExeSql Failed, Sql:%s",
				ssSql.str().c_str());
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_QUERY_FAILED,
				"QuerySql not exist, " "OpUin:%u MachineKey:%s Source:%s SceneId:%u",
				rCntlInfo.getOperatorUin(), strMachineKey.c_str(),
				strSource.c_str(), dwSceneId);
		C2C_WW_LOG_LAST_ERR_LOG(strErrmsg);
		return ERR_ERP_COMMON_DB_SELECT_FAILED;
	}
	do
	{
		erp::company::ddo::CCompanyInfoDdo oCompanyDdo;
		oCompanyDdo.SetCompanyCorporation(
				oRs.GetBigUInt("FCompanyCorporation"));
		oCompanyDdo.SetCompanyID(
				oRs.GetString("FCompanyID") ? oRs.GetString("FCompanyID") : "");
		oCompanyDdo.SetCompanyName(
				oRs.GetString("FCompanyName") ?
						oRs.GetString("FCompanyName") : "");

		oCompanyDdo.SetCompanySysNo(oRs.GetBigUInt("FCompanySysNo"));
		oCompanyDdo.SetCreatorSysNo(oRs.GetBigUInt("FCreatorSysNo"));

		oCompanyDdo.SetFCompanyProperty(oRs.GetUInt("FCompanyProperty"));
		oCompanyDdo.SetFCompanyStatus(oRs.GetUInt("FCompanyStatus"));
		oCompanyDdo.SetModifierSysNo(oRs.GetBigUInt("FModifierSysNo"));

		oCompanyDdo.SetRowCreatDate(oRs.GetBigUInt("FRowCreatDate"));
		oCompanyDdo.SetRowModifyDate(oRs.GetBigUInt("FRowModifyDate"));

		oCompanyDdo.SetTableID(
				oRs.GetString("FTableID") ? oRs.GetString("FTableID") : "");

		mapCompanyInfo[oCompanyDdo.GetCompanySysNo()()] = oCompanyDdo;
	} while (oRs.Next());
	oRs.Close();
	return dwRet;
}

/**
 *
 *  获取用户企业信息
 *
 *@param String machineKey: 机器码，必填   [in]
 *@param String source: 调用来源，必填   [in]
 *@param uint32_t sceneId: 场景id，必填   [in]
 *@param CompanyFilterDdo companyFilter: 过滤器，必填   [in]
 *@param String inReserve: 请求保留字   [in]
 *@param String errmsg: 错误信息  	[out]
 *@param Vector companyInfo: 员工信息  	[out]
 *@param String outReserve: 返回保留字   	[out]
 *
 *@return  uint32_t : 0(成功) 其它失败
 *
 */
uint32_t CCompanyDao::GetCompany(const CCntlInfo& rCntlInfo,
		const std::string& strMachineKey, const std::string& strSource,
		uint32_t dwSceneId,
		const erp::company::ddo::CCompanyFilterDdo& oCompanyFilter,
		const std::string& strInReserve, std::string& strErrmsg,
		std::vector<erp::company::ddo::CCompanyInfoDdo>& vecCompanyInfo,
		std::string& strOutReserve)
{
	uint32_t dwRet = 0;
	//TODO:业务代码
	uint16_t iSetId = 0;
	m_dwOperatorUin = rCntlInfo.getOperatorUin();
	m_dwSceneId = dwSceneId;
	m_strMachineKey = strMachineKey;
	m_strSource = strSource;

	C2C_WW_LOG("GetAReq %s OpUin:%u MachineKey:%s Source:%s SceneId:%u",
			__FUNCTION__, m_dwOperatorUin, strMachineKey.c_str(),
			strSource.c_str(), dwSceneId);

	//打印性能日志的同时进行接口的itil上报
	C2C_TIME_ELF_ITILoWTimeElf(C2C_WWLOG,__FUNCTION__,&dwRet,&m_oGetCompanyByIds);

	c2cent::storage::CMySqlStorage oStorage(CDAL_SET->GetDBOperator(rCntlInfo.getCmdId(),
			rCntlInfo.getOperatorUin(), DB_ROLE_NAME_COMPANY, TABLE_NAME_COMPANYREGISTER, iSetId, true));
	std::stringstream ssSql;

	ssSql
			<< "SELECT FCompanySysNo,FCompanyName,FCompanyCorporation,FCompanyID,FTableID,FCompanyProperty,FCompanyStatus,";
	ssSql
			<< " FCreatorSysNo,UNIX_TIMESTAMP(FRowCreatDate) ,FModifierSysNo,UNIX_TIMESTAMP(FRowModifyDate) FROM";
	ssSql << " " << TABLE_NAME_COMPANYREGISTER;

	//排除已经逻辑删除的数据
	ssSql << " WHERE FCompanyStatus<>0";

	if (oCompanyFilter.IsCompanyNameSet())
	{
		ssSql << " AND FCompanyName Like '%" << oCompanyFilter.GetCompanyName()
				<< "%'";

	}

	if (oCompanyFilter.IsCompanyCorporationSet())
	{
		ssSql << " AND FCompanyCorporation Like '%"
				<< oCompanyFilter.GetCompanyCorporation() << "%'";

	}
	if (oCompanyFilter.IsCompanyIDSet())
	{
		ssSql << " AND FCompanyID Like '%" << oCompanyFilter.GetCompanyID()
				<< "%'";

	}
	if (oCompanyFilter.IsTableIDSet())
	{
		ssSql << " AND FTableID Like '%" << oCompanyFilter.GetTableID() << "%'";

	}

	IResultSet& oRs = oStorage.QueryForResultSet(ssSql.str());
	C2C_WW_LOG_DEBUG("ExeSql Passed, Sql:%s", ssSql.str().c_str());

	if (!oRs.IsReady()) //db操作错误
	{
		oRs.Close();
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_SELECT_FAILED, "ExeSql Failed, Sql:%s",
				ssSql.str().c_str());
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_SELECT_FAILED,
				"ExeSql Failed, OpUin:%u MachineKey:%s Source:%s SceneId:%u",
				rCntlInfo.getOperatorUin(), strMachineKey.c_str(),
				strSource.c_str(), dwSceneId);
		C2C_WW_LOG_LAST_ERR_LOG(strErrmsg);
		return ERR_ERP_COMMON_DB_SELECT_FAILED;
	}

	if (!oRs.First() || oRs.GetRecordCount() == 0) //无记录
	{
		oRs.Close();
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_SELECT_FAILED, "ExeSql Failed, Sql:%s",
				ssSql.str().c_str());
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_QUERY_FAILED,
				"QuerySql not exist, " "OpUin:%u MachineKey:%s Source:%s SceneId:%u",
				rCntlInfo.getOperatorUin(), strMachineKey.c_str(),
				strSource.c_str(), dwSceneId);
		C2C_WW_LOG_LAST_ERR_LOG(strErrmsg);
		return ERR_ERP_COMMON_DB_SELECT_FAILED;
	}
	do
	{
		erp::company::ddo::CCompanyInfoDdo oCompanyDdo;
		oCompanyDdo.SetCompanyCorporation(
				oRs.GetBigUInt("FCompanyCorporation"));
		oCompanyDdo.SetCompanyID(
				oRs.GetString("FCompanyID") ? oRs.GetString("FCompanyID") : "");
		oCompanyDdo.SetCompanyName(
				oRs.GetString("FCompanyName") ?
						oRs.GetString("FCompanyName") : "");

		oCompanyDdo.SetCompanySysNo(oRs.GetBigUInt("FCompanySysNo"));
		oCompanyDdo.SetCreatorSysNo(oRs.GetBigUInt("FCreatorSysNo"));

		oCompanyDdo.SetFCompanyProperty(oRs.GetUInt("FCompanyProperty"));
		oCompanyDdo.SetFCompanyStatus(oRs.GetUInt("FCompanyStatus"));
		oCompanyDdo.SetModifierSysNo(oRs.GetBigUInt("FModifierSysNo"));

		oCompanyDdo.SetRowCreatDate(oRs.GetBigUInt("FRowCreatDate"));
		oCompanyDdo.SetRowModifyDate(oRs.GetBigUInt("FRowModifyDate"));

		oCompanyDdo.SetTableID(
				oRs.GetString("FTableID") ? oRs.GetString("FTableID") : "");

		vecCompanyInfo[oCompanyDdo.GetCompanySysNo()()] = oCompanyDdo;
	} while (oRs.Next());
	oRs.Close();

	return dwRet;
}

/**
 *
 *  写入&更新用户企业信息
 *
 *@param String machineKey: 机器码，必填   [in]
 *@param String source: 调用来源，必填   [in]
 *@param uint32_t sceneId: 场景id，必填   [in]
 *@param CompanyInfoDdo companyInfo: 员工信息列表，必填   [in]
 *@param String inReserve: 请求保留字   [in]
 *@param String errmsg: 错误信息  	[out]
 *@param String outReserve: 返回保留字   	[out]
 *
 *@return  uint32_t : 0(成功) 其它失败
 *
 */
uint32_t CCompanyDao::AddAndUpdateCompany(const CCntlInfo& rCntlInfo,
		const std::string& strMachineKey, const std::string& strSource,
		uint32_t dwSceneId,
		const erp::company::ddo::CCompanyInfoDdo& oCompanyInfo,
		const std::string& strInReserve, std::string& strErrmsg,
		std::string& strOutReserve)
{
	uint32_t dwRet = 0;
	//TODO:业务代码
	m_dwOperatorUin = rCntlInfo.getOperatorUin();
	m_dwSceneId = dwSceneId;
	m_strMachineKey = strMachineKey;
	m_strSource = strSource;
	C2C_WW_LOG("GetAReq %s OpUin:%u MachineKey:%s Source:%s SceneId:%u",
			__FUNCTION__, m_dwOperatorUin, strMachineKey.c_str(),
			strSource.c_str(), dwSceneId);

	//打印性能日志的同时进行接口的itil上报
	C2C_TIME_ELF_ITILoWTimeElf(C2C_WWLOG,__FUNCTION__,&iRetCode,&m_oAddAndUpdateBankAccount);

	c2cent::storage::CMySqlStorage oStorage(CDAL_SET->GetDBOperator(rCntlInfo.getCmdId(),
			rCntlInfo.getOperatorUin(), DB_ROLE_NAME_ACAccount, TABLE_NAME_BUSINESSUNITS ,iSetId, true));

	std::stringstream sql;

	//插入或者更新一条记录
	sql << " INSERT INTO ";
	sql << " " << TABLE_NAME_COMPANYREGISTER;
	sql
			<< " (FCompanySysNo,FCompanyName,FCompanyCorporation,FCompanyID,FTableID,FCompanyProperty,FCompanyStatus,";
	sql << "FCreatorSysNo,FRowCreatDate,FModifierSysNo,FRowModifyDate) ";
	sql << " VALUES( ";

	sql << " " << oCompanyInfo.GetCompanySysNo() << ", "; //bigint unsigned
	sql << "'" << oStorage.EscapeString(oCompanyInfo.GetCompanyName()) << "',"; //varchar 60
	sql << "'" << oStorage.EscapeString(oCompanyInfo.GetCompanyCorporation())
			<< "',"; //varchar 100
	sql << "'" << oStorage.EscapeString(oCompanyInfo.GetCompanyID()) << "',"; //varchar 100
	sql << "'" << oStorage.EscapeString(oCompanyInfo.GetTableID()) << "',"; //varchar 400

	sql << " " << oCompanyInfo.GetCompanyProperty() << ", "; //int unsigned
	sql << " " << oCompanyInfo.GetCompanyStatus()() << ", "; //int unsigned
	sql << " " << oCompanyInfo.GetCreatorSysNo() << ", "; //int unsigned
	sql << " " << "now(), "; //int unsigned
	sql << " " << oCompanyInfo.GetModifierSysNo() << ", "; //int unsigned
	sql << " " << "now(), "; //int unsigned

	sql << " ) ON DUPLICATE KEY UPDATE ";

	/*if (oCompanyInfo.IsCompanySysNoSet())
	 {
	 sql << " FCompanySysNo=VALUES(FCompanySysNo), ";
	 }
	 */
	if (oCompanyInfo.IsCompanyNameSet())
	{
		sql << " FCompanyName=VALUES(FCompanyName), ";
	}

	if (oCompanyInfo.IsCompanyCorporationSet())
	{
		sql << " FCompanyCorporation=VALUES(FCompanyCorporation), ";
	}
	if (oCompanyInfo.IsCompanyIDSet())
	{
		sql << " FCompanyID=VALUES(FCompanyID), ";
	}
	if (oCompanyInfo.IsTableIDSet())
	{
		sql << " FTableID=VALUES(FTableID), ";
	}
	if (oCompanyInfo.IsCompanyPropertySet())
	{
		sql << " FCompanyProperty=VALUES(FCompanyProperty), ";
	}
	if (oCompanyInfo.IsCompanyStatusSet()()())
	{
		sql << " FCompanyStatus=VALUES(FCompanyStatus), ";
	}

	sql << " FRowModifyDate=now() ";
	C2C_WW_LOG_DEBUG("sql:%s", sql.str().c_str()); //debug

	dwRet = oStorage.Update(sql.str());

	if (dwRet != 0)
	{
		//错误日志
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_INSERT_FAILED, "ExeSql Failed, Sql:%s",
				sql.str().c_str());
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_INSERT_FAILED,
				"ExeSql Failed, OpUin:%u MachineKey:%s Source:%s SceneId:%u BusinessUnitsSysNo:%ld",
				rCntlInfo.getOperatorUin(), strMachineKey.c_str(),
				strSource.c_str(), dwSceneId,
				oCompanyInfo.GetCompanySysNo());
		return ERR_ERP_COMMON_DB_INSERT_FAILED;
	}

	//删除操作没有操作到任何一条数据
	if (oStorage.GetAffectedRows() == 0)
	{
		//错误日志
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_AFFECTED_ZERO_FAILED,
				"ExeSql Update None, Sql:%s", sql.str().c_str());
		C2C_WW_LOG_ERR(ERR_ERP_COMMON_DB_AFFECTED_ZERO_FAILED,
				"ExeSql Failed, OpUin:%u MachineKey:%s Source:%s SceneId:%u BusinessUnitsSysNo:%ld",
				rCntlInfo.getOperatorUin(), strMachineKey.c_str(),
				strSource.c_str(), dwSceneId,
				oCompanyInfo.GetCompanySysNo());
		return ERR_ERP_COMMON_DB_AFFECTED_ZERO_FAILED;
	}
	return dwRet;
}

/**
 *
 *  逻辑删除用户企业信息
 *
 *@param String machineKey: 机器码，必填   [in]
 *@param String source: 调用来源，必填   [in]
 *@param uint32_t sceneId: 场景id，必填   [in]
 *@param CompanyInfoDdo companyInfo: 用户企业信息列表，必填   [in]
 *@param String inReserve: 请求保留字   [in]
 *@param String errmsg: 错误信息  	[out]
 *@param String outReserve: 返回保留字   	[out]
 *
 *@return  uint32_t : 0(成功) 其它失败
 *
 */
uint32_t CCompanyDao::DeleteCompany(const CCntlInfo& rCntlInfo,
		const std::string& strMachineKey, const std::string& strSource,
		uint32_t dwSceneId,
		const erp::company::ddo::CCompanyInfoDdo& oCompanyInfo,
		const std::string& strInReserve, std::string& strErrmsg,
		std::string& strOutReserve)
{
	uint32_t dwRet = 0;
	//TODO:业务代码

	return dwRet;
}
